package com.supreme.studyserver.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.incrementer.OracleKeyGenerator;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.supreme.studyserver.config.handler.MybatisSuperInterceptor;
import com.supreme.studyserver.threadstore.ThreadStore;
import lombok.Data;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.schema.Column;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;
import java.util.Optional;

@Data
@ConfigurationProperties(value = "supreme.config")
@Configuration
@MapperScan(value = {"com.supreme.studyserver.mapper"})
public class MybatisPlusConfig {

    private Boolean tenantEnabled;
    private String tenantKey;
    private List<String> ignoreTables;

    @Bean
    public OracleKeyGenerator oracleKeyGenerator() {
        return new OracleKeyGenerator();
    }

    @Bean MybatisSuperInterceptor mybatisSuperInterceptor() {
        return new MybatisSuperInterceptor();
    }

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(MybatisSuperInterceptor mybatisSuperInterceptor) {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        interceptor.addInnerInterceptor(paginationInnerInterceptor);

        OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor = new OptimisticLockerInnerInterceptor();
        interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor);

        if (this.tenantEnabled) {
            TenantLineInnerInterceptor tenantLineInnerInterceptor = new TenantLineInnerInterceptor();
            tenantLineInnerInterceptor.setTenantLineHandler(new TenantLineHandler() {
                @Override
                public Expression getTenantId() {
                    if (ThreadStore.getStore() != null) {
                        final ThreadStore.Store store = ThreadStore.getStore();
                        return new LongValue(store.getClientId());
                    }
                    return new LongValue(1);
                }

                @Override
                public String getTenantIdColumn() {
                    return tenantKey;
                }

                @Override
                public boolean ignoreTable(String tableName) {
                    final Optional<String> optional = ignoreTables.stream()
                            .filter(tableItem -> tableItem.equals(tableName))
                            .findFirst();
                    return optional.isPresent();
                }

                @Override
                public boolean ignoreInsert(List<Column> columns, String tenantIdColumn) {
                    return TenantLineHandler.super.ignoreInsert(columns, tenantIdColumn);
                }
            });
            interceptor.addInnerInterceptor(tenantLineInnerInterceptor);
        }

//        interceptor.addInnerInterceptor(mybatisSuperInterceptor);

        return interceptor;
    }
}